﻿using System;
using System.Collections.Generic;
using System.Text;
using AMS.DataAccess.Sys.BO;
using AMS.DataAccess.Sql;
using AMS.DataAccess.Common;
using AMS.DataAccess.Sys.Interfaces;
using AMS.DataAccess.Sys.Filters;
using System.Data;

namespace AMS.DataAccess.Sys
{
    public class UserManager : IUserManager
    {
        const string UserTable = "TU_User";
        public void AddUser(CallContext context, UserInfo user)
        {
            if (user.CreateUserID == 0)
            {
                user.CreateUserID = context.UserID;
                user.CreateDateTime = DateTime.Now;
            }

            SqlInsert insert = new SqlInsert(UserTable);
            insert.AddBusinessObject(user);
            insert.Add("SELECT @@IDENTITY");
#if SHOW_SQL
            System.Diagnostics.Debug.WriteLine(insert.ToString());
#endif
            var ds = SqlDBHelper.Query(insert.ToString());
            user.AID = Convert.ToInt32(ds.Tables[0].Rows[0][0]);
        }

        public bool UpdateUser(CallContext context, UserInfo user)
        {
            if (user.ModifiedDateTime == DateTime.MinValue)
            {
                user.ModifiedDateTime = DateTime.Now;
            }

            if (user.ModifiedUserID == 0)
            {
                user.ModifiedUserID = context.UserID;
            }

            SqlUpdate update = new SqlUpdate(UserTable);
            update.AddBusinessObject(user);
            if (user.Version >= 0)
            {
                update.AddVersionColumn();
            }

            update.AddCondition("    ", new SqlCondition("AID", user.AID));
#if SHOW_SQL
            System.Diagnostics.Debug.WriteLine(update.ToString());
#endif
            return (0 < SqlDBHelper.ExecuteSql(update.ToString()));
        }

        public List<UserInfo> GetActiveUsers(CallContext context)
        {
            SqlBuilder sql = new SqlBuilder();
            sql.Add("SELECT *");
            sql.Add("FROM ", UserTable);
            sql.Add("WHERE ", new SqlCondition("isSysUser", 0));
            sql.Add("    AND ", new SqlCondition("ActiveFlag", 0));
            sql.Add("    ORDER BY Name ASC");
#if SHOW_SQL
            System.Diagnostics.Debug.WriteLine(sql.ToString());
#endif
            var ds = SqlDBHelper.Query(sql.ToString());
            var list = BusinessObjectMapping.DataTableToBOList<UserInfo>(ds.Tables[0]);
            return list;
        }

        public List<UserInfo> GetTrademarkAttoneys(CallContext context, bool queryExtentedInfo)
        {
            SqlBuilder sql = new SqlBuilder();
            sql.Add("SELECT AID, Name, WorkNumber");
            if (queryExtentedInfo)
            {
                sql.Add("      ,[Alias]");
                sql.Add("      ,[isSysUser]");
                sql.Add("      ,[Sex]");
                sql.Add("      ,[LoginName]");
                sql.Add("      ,[Pwd]");
                sql.Add("      ,[PwdExpireDate]");
                sql.Add("      ,[IDCard]");
                sql.Add("      ,[Birthday]");
                sql.Add("      ,[ActiveFlag]");
                sql.Add("      ,[isReadOnly]");
                sql.Add("      ,[Mobile]");
                sql.Add("      ,[Tel]");
                sql.Add("      ,[Email]");
                sql.Add("      ,[QQ]");
                sql.Add("      ,[MSN]");
                sql.Add("      ,[Note]");
                sql.Add("      ,[Picture]");
                sql.Add("      ,[isPatentAttoney]");
                sql.Add("      ,[isTrademarkAttoney]");
                sql.Add("      ,[CreateDateTime]");
                sql.Add("      ,[CreateUserID]");
                sql.Add("      ,[ModifiedDateTime]");
                sql.Add("      ,[ModifiedUserID]");
                sql.Add("      ,[Version]");
            }

            sql.Add("FROM ", UserTable);
            sql.Add("WHERE ",  new SqlCondition("isSysUser", false));
            sql.Add("    AND ", new SqlCondition("ActiveFlag", 0));
            sql.Add("    AND ", new SqlCondition("isTrademarkAttoney", true));
#if SHOW_SQL
            System.Diagnostics.Debug.WriteLine(sql.ToString());
#endif
            var ds = SqlDBHelper.Query(sql.ToString());
            var list = BusinessObjectMapping.DataTableToBOList<UserInfo>(ds.Tables[0]);
            return list;
        }

        public bool UpdateUserPassword(CallContext context, int userId, string newPassword)
        {
            SqlBuilder sql = new SqlBuilder();
            sql.Add("UPDATE ", UserTable);
            sql.Add("SET");
            sql.Add("    ", new SqlExpression("Pwd", newPassword));
            sql.Add("WHERE ", new SqlCondition("AID", userId));
#if SHOW_SQL
            System.Diagnostics.Debug.WriteLine(sql.ToString());
#endif
            return 0 < SqlDBHelper.ExecuteSql(sql.ToString());
        }

        public UserInfo GetUser(CallContext context, int userId)
        {
            SqlBuilder sql = new SqlBuilder();
            sql.Add("SELECT * FROM ", UserTable);
            sql.Add("WHERE ", new SqlCondition("AID", userId));
#if SHOW_SQL
            System.Diagnostics.Debug.WriteLine(sql.ToString());
#endif
            var ds = SqlDBHelper.Query(sql.ToString());
            if (ds.Tables[0].Rows.Count > 0)
            {
                UserInfo user = BusinessObjectMapping.DataRowToBO<UserInfo>(ds.Tables[0].Rows[0]);
                return user;
            }
            else
            {
                return null;
            }
        }

        public List<UserInfo> GetPagedUsers(CallContext context, UserFilter filter, int pageIndex, int pageSize)
        {
            int total;
            return GetPagedUsers(context, filter, pageIndex, pageSize, false, out total);
        }

        public List<UserInfo> GetPagedUsers(CallContext context, UserFilter filter, int pageIndex, int pageSize, out int totalCount)
        {
            return GetPagedUsers(context, filter, pageIndex, pageSize, true, out totalCount);
        }

        private List<UserInfo> GetPagedUsers(CallContext context, UserFilter filter, int pageIndex, int pageSize, bool caculateTotal, out int totalCount)
        {
            SqlBuilder sql = new SqlBuilder();
            sql.Add("SELECT * FROM ", UserTable);
            sql.Add("WHERE 1=1");
            // TODO: 为了调试，去掉了这个条件
            //ApplyFilter(sql, filter);

            SqlInfo sqlInfo = new SqlInfo();
            sqlInfo.BaseSql = sql.ToString();
            sqlInfo.PKField = "AID";

            PagedSqlInfo pagedSql = new PagedSqlInfo();
            PagerWrapper.WrapSql(sqlInfo, new PagerInfo(pageIndex, pageSize), ref pagedSql);
#if SHOW_SQL
            System.Diagnostics.Debug.WriteLine(pagedSql.PagedSql);
#endif
            var ds = SqlDBHelper.Query(pagedSql.PagedSql.ToString());
            var list = BusinessObjectMapping.DataTableToBOList<UserInfo>(ds.Tables[0]);
            if (caculateTotal)
            {
                var totalDS = SqlDBHelper.Query(pagedSql.TotalCountSql);
                totalCount = AdoConverter.ToInt32(totalDS.Tables[0].Rows[0][0]);
            }
            else
            {
                totalCount = 0;
            }

            return list;
        }

        void ApplyFilter(SqlBuilder sql, UserFilter filter)
        {
            if (filter == null)
            {
                return;
            }

            if (!filter.QuerySysUser)
            {
                sql.Add("    AND isSysUser = 0");
            }
            if (!filter.QueryInactiveUser)
            {
                sql.Add("    AND ", new SqlEnumCondition<ActiveFlag>("ActiveFlag", ActiveFlag.Active));
            }
            if (filter.IsPatentAttoney != null)
            {
                sql.Add("    AND isPatentAttoney", filter.IsPatentAttoney.ToString());
            }
            if (filter.IsTrademarkAttoney != null)
            {
                sql.Add("    AND isTrademarkAttoney", filter.IsTrademarkAttoney.ToString());
            }
            if (filter.LoginName != null)
            {
                sql.Add("    AND LoginName", filter.LoginName.ToString());
            }
            if (filter.Name != null)
            {
                sql.Add("    AND Name", filter.Name.ToString());
            }
            if (filter.Sex != null)
            {
                sql.Add("    AND Sex", filter.Sex.ToString());
            }
            if (filter.WorkNumber != null)
            {
                sql.Add("    AND WorkNumber", filter.WorkNumber.ToString());
            }
        }

        public int BatchSetUsersInactive(CallContext context, ICollection<int> userIDs)
        {
            SqlUpdate update = new SqlUpdate(UserTable);
            update.AddColumn("ActiveFlag", (int)ActiveFlag.Inactive);
            update.AddColumn("ModifiedDateTime", DateTime.Now, DateTimeType.DateTime);
            // TODO: enabled user id
            //sql.AddColumn("ModifiedUserID", context.UserID);
            SqlConditionList list = new SqlConditionList("AID", userIDs);
            update.AddCondition(list.ToString());
            update.AddCondition("isReadOnly = 0");
#if SHOW_SQL
            System.Diagnostics.Debug.WriteLine(update.ToString());
#endif
            return SqlDBHelper.ExecuteSql(update.ToString());
        }

        public List<UserInfo> GetUsersByRole(CallContext context, int roleId)
        {
            SqlBuilder sql = new SqlBuilder();
            sql.Add("SELECT u.* FROM TS_UserRole ur");
            sql.Add("INNER JOIN TS_User u ON ur.UserID = u.AID");
            sql.Add("WHERE ", new SqlCondition("ur.RoleID", roleId));
#if SHOW_SQL
            System.Diagnostics.Debug.WriteLine(sql.ToString());
#endif
            var ds = SqlDBHelper.Query(sql.ToString());
            var list = BusinessObjectMapping.DataTableToBOList<UserInfo>(ds.Tables[0]);
            return list;
        }

        public List<UserInfo> GetUsersExcludedOfRole(CallContext context, int roleId)
        {
            SqlBuilder sql = new SqlBuilder();
            sql.Add("SELECT * FROM ", UserTable);
            sql.Add("WHERE ActiveFlag = 0");
            sql.Add("    AND AID NOT IN(");
            sql.Add("    SELECT ur.UserID FROM TS_UserRole ur");
            sql.Add("    WHERE ", new SqlCondition("ur.RoleID", roleId));
            sql.Add("    )");
#if SHOW_SQL
            System.Diagnostics.Debug.WriteLine(sql.ToString());
#endif
            var ds = SqlDBHelper.Query(sql.ToString());
            var list = BusinessObjectMapping.DataTableToBOList<UserInfo>(ds.Tables[0]);
            return list;
        }

        public Dictionary<string, int> GetUserPrivilages(CallContext context, int userId)
        {
            return GetUserPrivilages(context, userId, 0);
        }

        public Dictionary<string, int> GetUserPrivilages(CallContext context, int userId, int moduleId)
        {
            SqlBuilder sql = new SqlBuilder();
            sql.Add("SELECT DISTINCT p.FunctionID, f.FunctionKey");
            sql.Add("FROM TS_UserRole ur");
            sql.Add("INNER JOIN TS_Privilage p ON ur.RoleID = p.RoleID");
            sql.Add("INNER JOIN TS_Function f on f.AID = p.FunctionID");
            sql.Add("WHERE ", new SqlCondition("ur.UserID", userId));
            if (moduleId != 0)
            {
                sql.Add("    AND ", new SqlCondition("f.ModuleID", moduleId));
            }
#if SHOW_SQL
            System.Diagnostics.Debug.WriteLine(sql.ToString());
#endif
            var ds = SqlDBHelper.Query(sql.ToString());
            Dictionary<string, int> functions = new Dictionary<string, int>();
            foreach (DataRow row in ds.Tables[0].Rows)
            {
                functions.Add(AdoConverter.ToString(row["FunctionKey"]), AdoConverter.ToInt32(row["FunctionKey"]));
            }

            return functions;
        }


        public List<FunctionInfo> GetPriorityFunctions(CallContext context, int userID)
        {
            SqlBuilder sql = new SqlBuilder();
            sql.Add("SELECT f.* FROM TS_User u");
            sql.Add("INNER JOIN TS_UserFunctionPrio uf ON u.AID = uf.UserID");
            sql.Add("INNER JOIN TS_Function f ON uf.FunctionID = f.AID");
            sql.Add("WHERE ", new SqlExpression("u.AID", userID));

#if SHOW_SQL
            System.Diagnostics.Debug.WriteLine(sql.ToString());
#endif

            var ds = SqlDBHelper.Query(sql.ToString());
            var functions = BusinessObjectMapping.DataTableToBOList<FunctionInfo>(ds.Tables[0]);
            return functions;
        }

        public int BatchUpdatePriorityFunctions(CallContext context, int userID, IList<int> addedList, IList<int> deletedList)
        {
            SqlBatch batch = new SqlBatch();
            if (addedList != null && addedList.Count > 0)
            {
                foreach (int functionID in addedList)
                {
                    SqlInsert sql = new SqlInsert("TS_UserFunctionPrio");
                    sql.AddColumn("UserID", userID);
                    sql.AddColumn("FunctionID", functionID);
                    batch.Add(sql);
                }
            }

            if (deletedList != null && deletedList.Count > 0)
            {
                foreach(int functionID in deletedList)
                {
                    SqlDelete sql = new SqlDelete("TS_UserFunctionPrio");
                    sql.AddCondition(new SqlCondition("UserID", userID));
                    sql.AddCondition(new SqlCondition("FunctionID", functionID));
                    batch.Add(sql);
                }
            }

           #if SHOW_SQL
            System.Diagnostics.Debug.WriteLine(batch.ToString());
#endif

            return SqlDBHelper.ExecuteSql(batch.ToString());
        }
    }
}

